package com.ukefu.webim.service.es;

import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.index.query.QueryStringQueryBuilder.Operator;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Component;

import com.ukefu.webim.web.model.Contacts;

@Component
public class ContactsRepositoryImpl implements ContactsEsCommonRepository{
	private ElasticsearchTemplate elasticsearchTemplate;

	@Autowired
	public void setElasticsearchTemplate(ElasticsearchTemplate elasticsearchTemplate) {
		this.elasticsearchTemplate = elasticsearchTemplate;
    }

	@Override
	public Page<Contacts> findByCreaterAndSharesAndOrgi(String creater, String shares ,String orgi, boolean includeDeleteData ,String q , Pageable page) {
		
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		BoolQueryBuilder boolQueryBuilder1 = new BoolQueryBuilder();
		boolQueryBuilder1.should(termQuery("creater" , creater)) ;
		boolQueryBuilder1.should(termQuery("shares" , creater)) ;
		boolQueryBuilder1.should(termQuery("shares" , "all")) ;
		boolQueryBuilder.must(boolQueryBuilder1) ;
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		if(includeDeleteData){
			boolQueryBuilder.must(termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		}
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		return processQuery(boolQueryBuilder , page);
	}
	
	@Override
	public Page<Contacts> findByCreaterAndSharesAndOrgi(String creater,
			String shares,String orgi, Date begin, Date end, boolean includeDeleteData,
			BoolQueryBuilder boolQueryBuilder , String q, Pageable page) {
		BoolQueryBuilder boolQueryBuilder1 = new BoolQueryBuilder();
		boolQueryBuilder1.should(termQuery("creater" , creater)) ;
		boolQueryBuilder1.should(termQuery("shares" , creater)) ;
		boolQueryBuilder1.should(termQuery("shares" , "all")) ;
		boolQueryBuilder.must(boolQueryBuilder1) ;
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		if(includeDeleteData){
			boolQueryBuilder.must(termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		}
		RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("createtime") ;
		if(begin!=null){
			rangeQuery.from(begin.getTime()) ;
		}
		if(end!=null){
			rangeQuery.to(end.getTime()) ;
		}else{
			rangeQuery.to(new Date().getTime()) ;
		}
		if(begin!=null || end!=null){
			boolQueryBuilder.must(rangeQuery) ;
		}
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		return processQuery(boolQueryBuilder , page);
	}
	
	@Override
	public Page<Contacts> findByOrgi(String orgi, boolean includeDeleteData,
			String q, Pageable page) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		if(includeDeleteData){
			boolQueryBuilder.must(termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		}
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		return processQuery(boolQueryBuilder , page);
	}

	@Override
	public Page<Contacts> findByCreaterAndSharesAndOrgi(String creater,String shares,String orgi, Date begin, Date end, boolean includeDeleteData,String q, Pageable page) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		BoolQueryBuilder boolQueryBuilder1 = new BoolQueryBuilder();
		boolQueryBuilder1.should(termQuery("creater" , creater)) ;
		boolQueryBuilder1.should(termQuery("shares" , creater)) ;
		boolQueryBuilder1.should(termQuery("shares" , "all")) ;
		boolQueryBuilder.must(boolQueryBuilder1) ;
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		if(includeDeleteData){
			boolQueryBuilder.must(termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		}
		RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("createtime") ;
		if(begin!=null){
			rangeQuery.from(begin.getTime()) ;
		}
		if(end!=null){
			rangeQuery.to(end.getTime()) ;
		}else{
			rangeQuery.to(new Date().getTime()) ;
		}
		if(begin!=null || end!=null){
			boolQueryBuilder.must(rangeQuery) ;
		}
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		return processQuery(boolQueryBuilder , page);
	}
	
	
	private Page<Contacts> processQuery(BoolQueryBuilder boolQueryBuilder, Pageable page){
		NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder().withQuery(boolQueryBuilder).withSort(new FieldSortBuilder("createtime").unmappedType("date").order(SortOrder.DESC));
		
		if (page != null) {
			searchQueryBuilder.withPageable(page) ;
		}
		
		Page<Contacts> entCustomerList = null ;
		if(elasticsearchTemplate.indexExists(Contacts.class)){
			entCustomerList = elasticsearchTemplate.queryForPage(searchQueryBuilder.build() , Contacts.class) ;
		}
		return entCustomerList;
	}

	@Override
	public Page<Contacts> findByDataAndOrgi(String orgi, String q, Pageable page) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		return processQuery(boolQueryBuilder , page);
	}
	
	@Override
	public Page<Contacts> findByPhoneAndOrgi(String phone, String orgi, Pageable page) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		
		BoolQueryBuilder boolQueryBuilder1 = new BoolQueryBuilder();
		boolQueryBuilder1.should(termQuery("phone" , phone)) ;
		boolQueryBuilder1.should(termQuery("mobileno" , phone)) ;
		
		boolQueryBuilder.must(boolQueryBuilder1) ;
		return processQuery(boolQueryBuilder , page);
	}
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Override
	public void updateMapping() {
		Map m = elasticsearchTemplate.getMapping("uckefu", "uk_contacts");
		((Map)((Map)m.get("properties")).get("cusbirthday")).put("format", "yyyy-MM-dd HH:mm:ss");
		elasticsearchTemplate.putMapping("uckefu", "uk_contacts", m);
		System.out.println(m);
	}

	@Override
	public Page<Contacts> findByQueryAndOrgi(String ctype,String orgi, Date begin, Date end,
			boolean includeDeleteData, BoolQueryBuilder boolQueryBuilder, String q, Pageable page) {
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		if (!StringUtils.isBlank(ctype)) {
			boolQueryBuilder.must(termQuery("ctype" , ctype)) ;
		}
		if(includeDeleteData){
			boolQueryBuilder.must(termQuery("datastatus" , true)) ;
		}else{
			boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		}
		RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("createtime") ;
		if(begin!=null){
			rangeQuery.from(begin.getTime()) ;
		}
		if(end!=null){
			rangeQuery.to(end.getTime()) ;
		}else{
			rangeQuery.to(new Date().getTime()) ;
		}
		if(begin!=null || end!=null){
			boolQueryBuilder.must(rangeQuery) ;
		}
		if(!StringUtils.isBlank(q)){
	    	boolQueryBuilder.must(new QueryStringQueryBuilder(q).defaultOperator(Operator.AND)) ;
	    }
		return processQuery(boolQueryBuilder , page);
	}

	@Override
	public Page<Contacts> findByReservation(Pageable page) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(termQuery("datastatus" , false)) ;
		boolQueryBuilder.must(termQuery("reservation" ,true)) ;
		boolQueryBuilder.must(termQuery("processed" ,false)) ;
		
		boolQueryBuilder.must(rangeQuery("optime").to(System.currentTimeMillis())) ;
		
		boolQueryBuilder.must(QueryBuilders.existsQuery("owneruser")) ;
		return processQuery(boolQueryBuilder , page);
	}

	@Override
	public Contacts findByIdAndOrgi(String id, String orgi) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		boolQueryBuilder.must(termQuery("id" ,id)) ;
		boolQueryBuilder.must(termQuery("datastatus" ,false)) ;
		Page<Contacts> contactsPage = processQuery(boolQueryBuilder , null);
		Contacts contacts = null;
		if (contactsPage != null && contactsPage.getContent() != null && contactsPage.getContent().size() > 0) {
			contacts = contactsPage.getContent().get(0);
		}
		return contacts;
	}

	@Override
	public List<Contacts> findByIdInAndOrgi(List<String> ids, String orgi) {
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		if (ids != null && ids.size() > 0) {
			BoolQueryBuilder boolQueryBuilder1 = QueryBuilders.boolQuery();
			for(String id : ids) {
				if (!StringUtils.isBlank(id)) {
					boolQueryBuilder1.should(termQuery("id" ,id)) ;
				}
			}
			boolQueryBuilder.must(boolQueryBuilder1);
		}
		boolQueryBuilder.must(termQuery("orgi" ,orgi)) ;
		boolQueryBuilder.must(termQuery("datastatus" ,false)) ;
		Page<Contacts> contactsPage = processQuery(boolQueryBuilder , new PageRequest(0 , 10000));
		List<Contacts> contactsList = null;
		if (contactsPage != null && contactsPage.getContent() != null && contactsPage.getContent().size() > 0) {
			contactsList = contactsPage.getContent();
		}
		return contactsList;
	}
}
